package cn.scau.server.service.impl;

import cn.scau.server.dto.MobileLoginFormDTO;
import cn.scau.server.mapper.EmpMapper;
import cn.scau.server.pojo.Emp;
import cn.scau.server.service.MobileUserService;
import cn.scau.server.utils.MobileUserutils;
import cn.scau.server.vo.EmpPermissionVO;
import cn.scau.server.vo.ResultVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import static cn.scau.server.utils.RedisConstants.*;

@Service
@Transactional
public class MobileUserServiceImpl extends ServiceImpl<EmpMapper, Emp> implements MobileUserService {

    @Autowired
    private EmpMapper empMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    //todo 但是目前这些做法都是比较危险的（）后面要做优化的，因为目前就是很直白地把所有东西都放在前端了
    @Override
    public ResultVO login(MobileLoginFormDTO loginForm) {
        String empId = loginForm.getEmpId();
        String password = loginForm.getPassword();
        String redisKey = LOGIN_CODE_KEY + empId;
        String redisPassword = stringRedisTemplate.opsForValue().get(redisKey);

        if (redisPassword != null) {
            if (!redisPassword.equals(password)) {
                return ResultVO.fail("账号密码不匹配");
            }
        } else {
            EmpPermissionVO emp = empMapper.getEmpPermission(empId);
            if (emp == null) {
                return ResultVO.fail("此工号不存在！");
            }
            // todo 缓存穿透要小心
            QueryWrapper<Emp> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("emp_id", empId);
            Emp empRecord = getOne(queryWrapper);
            if (empRecord == null || !empRecord.getPassword().equals(password)) {
                return ResultVO.fail("密码不正确！");
            }
        }

        // 生成登录令牌
        EmpPermissionVO emp = empMapper.getEmpPermission(empId);
        String token = MobileUserutils.generateToken();
        Map<String, Object> userMap = MobileUserutils.empToMap(emp);
        if(userMap.isEmpty()){
            return ResultVO.fail("获取用户信息失败！");
        }
        //清空过期token
        clearToken(empId);

        // 存储用户信息和密码到 Redis
        stringRedisTemplate.opsForHash().putAll(LOGIN_USER_KEY + token, userMap);
        stringRedisTemplate.opsForValue().set(redisKey, password);

        // 设置 Redis 过期时间

        stringRedisTemplate.expire(LOGIN_USER_KEY + token, LOGIN_USER_TTL, TimeUnit.DAYS);
        stringRedisTemplate.expire(redisKey, LOGIN_CODE_TTL, TimeUnit.DAYS);

        return ResultVO.success("登录成功！", token);
    }

    private void clearToken(String empId) {
        // 清理旧的Token
        Set<String> keys = stringRedisTemplate.keys(LOGIN_USER_KEY + "*");
        if (keys != null) {
            for (String key : keys) {
                Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(key);
                if (userMap != null && empId.equals(userMap.get("empId"))) {
                    stringRedisTemplate.delete(key); // 删除旧的Token
                }
            }
        }
    }

    @Override
    public ResultVO getUserInfo(String empId, HttpServletRequest request) {
        // 从请求头中获取 token
        String token = request.getHeader("Authorization");
        if (token == null) {
            return ResultVO.fail("未登录或登录信息失效");
        }

        // 构造 Redis 键
        String key = LOGIN_USER_KEY + token;

        // 获取 Redis 操作对象
        HashOperations<String, String, Object> hashOperations = stringRedisTemplate.opsForHash();

        try {
            // 尝试从 Redis 中获取用户信息
            Map<String, Object> empMap = hashOperations.entries(key);
            if (empMap != null && !empMap.isEmpty()) {
                // 如果 Redis 中存在用户信息，直接返回
                return ResultVO.success("查询成功", empMap);
            } else {
                // 如果 Redis 中不存在用户信息，尝试从数据库中获取
                EmpPermissionVO emp = empMapper.getEmpPermission(empId);
                if (emp == null) {
                    // 如果数据库中也不存在用户信息，缓存不存在的用户信息并返回错误
                    hashOperations.put(key, "empId", null);
                    stringRedisTemplate.expire(key, 10, TimeUnit.MINUTES);
                    return ResultVO.fail("用户不存在");
                }

                // 将用户信息存储到 Redis 中，并设置有效期
                hashOperations.putAll(key, MobileUserutils.empToMap(emp));
                stringRedisTemplate.expire(key, LOGIN_USER_TTL, TimeUnit.DAYS);

                return ResultVO.success("查询成功", emp);
            }
        } catch (Exception e) {
            // 记录异常日志
            log.error("获取用户信息失败", e);
            return ResultVO.fail("系统异常，请稍后再试");
        }
    }

    @Override
    public ResultVO updateRedisPassword(String empId, String password) {
        String redisKey = LOGIN_CODE_KEY + empId;
        String redisPassword = stringRedisTemplate.opsForValue().get(redisKey);

        if (redisPassword != null) {
            if (redisPassword.equals(password)) {
                return ResultVO.success("更新成功");
            }else{
                stringRedisTemplate.delete(redisKey);
                stringRedisTemplate.opsForValue().set(redisKey, password);
                return ResultVO.success("更新成功");
            }
        }

        //如果redis中没有，那就让它去登录
        return ResultVO.fail("请先登录！");
    }
}
